<?php
define('REDIS_HOST', '127.0.0.1');
define('REDIS_PORT', 6379);
define('ROUTER_HOST', '127.0.0.1');
define('ROUTER_PORT', 9010);
define('TABLE_MAX', 100);
define('SEAT_MAX', 6);
define('CARD_MAX', 3);
define('FOOKING', isset($_SERVER['SESSIONID']) ? true : false);
if(FOOKING){
	define('SID', $_SERVER['SESSIONID']);
}else{
	define('SID', $_GET['sid']);
}

date_default_timezone_set('Asia/Shanghai');

require('api.php');

$event = empty($_SERVER['EVENT']) ? 0 : (int)$_SERVER['EVENT'];
if($event == 1){//connect
	//TODO
}else if($event == 2){//close
	//TODO
}else{
	if(FOOKING){
		$data = file_get_contents("php://input");
		$msg = unpackMsg($data);
		$type = $msg['type'];
		$data = $msg['data'];
	}else{
		$type = $_GET['type'];
		$data = $_GET;
	}
	runMsg($type, $data);
}

function runMsg($type, $data)
{
	$func = 'do' . $type;
	if(!function_exists($func)){
		echo "not found $func\n";
		return ;
	}

	$func($data);
}

//登陆
function doLogin($msg)
{
	$sid = SID;
	$redis = getRedis();
	$user = array(
		'sid' => $sid,
		'name' => $msg['name'],
		'time' => time(),
		'gold' => 100000,
	);
	$redis->hMSet("user:$sid", $user);
	response('login', $user);
}

//加入房间
function doJoin($msg)
{
}

//座下
function doSeat($msg)
{
	$sid = SID;
	$redis = getRedis();
	$tableid = $msg['tableid'];
	$seatid = $msg['seatid'];
	
	if($tableid < 1 || $tableid > TABLE_MAX || 
		$seatid < 1 || $seatid > SEAT_MAX){
		return false;
	}
	
	$gold = $redis->hget("user:$sid", "gold");
	if($gold < 10){
		response("join", array(
			"error" => 3
		));
		return false;
	}
	
	$ret = $redis->hsetnx("user:$sid", "tableid", $tableid);
	if(!$ret){
		response('join', array(
			'error' => 1
		));
		return false;
	}
	
	$ret = $redis->hsetnx("table:$tableid", "seat-$seatid", json_encode(array(
		"sid" => $sid,
		"time" => time(),
		'seat' => $seatid,
	)));
	if(!$ret){
		$redis->hdel("user:$sid", "tableid");
		
		response('join', array(
			'error' => 2
		));
		return false;
	}
	
	$redis->hset("user:$sid", "seatid", $seatid);
	
	$seatkeys = array();
	for($i = 1; $i <= SEAT_MAX; ++$i){
		$seatkeys[] = "seat-$i";
	}
	
	$seats = $redis->hMGet("table:$tableid", $seatkeys);
	$users = array();
	foreach($seats as $u){
		if(!$u) continue;
		$u = json_decode($u, true);
		$uid = $u['sid'];
		$user = $redis->hGetAll("user:$uid");
		$users[$uid] = $user;
	}
	
	if(count($users) == 1){
		//主机
		$redis->hset("table:$tableid", "master", $sid);
	}
	
	$router = getRouter();
	$router->publish("table:$tableid", packMsg("joinOne", $users[$sid]));//单个用户加入消息
	$router->addChannel("table:$tableid", $sid);
	
	response("join", array(
		'list' => $users
	));
}

//退出房间
function doLeave($msg)
{
	$sid = SID;
	$redis = getRedis();
	
	$user = $redis->hMget("user:$sid", array("tableid", "seatid"));
	if(!$user['tableid']){
		return false;
	}
	
	$tableid = $user['tableid'];
	$seatid = $user['seatid'];
	$table = $redis->hMget("table:$tableid", array("state", "master"));
	if($table['state']){
		return false;
	}
	
	if($table['master'] == $sid){
		//转交管理权
		$seatkeys = array();
		for($i = 1; $i <= SEAT_MAX; ++$i){
			$seatkeys[] = "seat-$i";
		}
		
		$master = "";
		$seats = $redis->hMGet("table:$tableid", $seatkeys);
		foreach($seats as $u){
			if(!$u) continue;
			$u = json_decode($u, true);
			if($u['sid'] != $sid){
				$master = $u['sid'];
				break;
			}
		}
		
		$redis->hset("table:$tableid", "master", $master);
	}
	
	$redis->hdel("table:$tableid", "seat-$seatid");
	$redis->hdel("user:$sid", "tableid");
	$redis->hdel("user:$sid", "seatid");
	
	$router = getRouter();
	$router->publish("table:$tableid", packMsg("leave", array('sid' => $sid)));
	$router->delChannel("table:$tableid", $sid);
}

//开始
function doStart($msg)
{
	$sid = SID;
	$redis = getRedis();
	
	$tableid = $redis->hget("user:$sid", "tableid");
	if(!$tableid){
		return false;
	}
	
	$table = $redis->hMget("table:$tableid", array("master", "state"));
	if($table['master'] != $sid){
		return false;
	}
	
	if($table['state']){
		return false;
	}
	
	$seatkeys = array();
	for($i = 1; $i <= SEAT_MAX; ++$i){
		$seatkeys[] = "seat-$i";
	}
	
	//get all seats
	$seats = $redis->hMGet("table:$tableid", $seatkeys);
	foreach($seats as $k => $u){
		if(!$u) unset($seats[$k]);
	}
	
	//check number
	if(count($seats) < 2){
		return false;
	}
	
	//give card
	$offset = 0;
	$update = array();
	$cards = makeCard();
	$seatsid = array();
	foreach($seats as $k => $u){
		$u = json_decode($u, true);
		$u['state'] = 0;
		$u['point'] = 2;
		$u['cards'] = array_slice($cards, $offset, CARD_MAX);
		$offset+= CARD_MAX;
		
		$update[$k] = json_encode($u);
		$seatsid[] = $u['seat'];
	}
	
	$update['current'] = 0;
	$update['state'] = 1;
	$update['point'] = 2;
	$update['total'] = count($seats) * 2;
	$update['seats'] = implode(',', $seatsid);
	$update['users'] = count($seats);
	$redis->hmset("table:$tableid", $update);
	
	$router = getRouter();
	$router->publish("table:$tableid", packMsg("start", array(
		'current' => 0,
	)));
}

//看牌
function doLook($msg)
{
	$sid = SID;
	$redis = getRedis();
	
	$user = $redis->hMget("user:$sid", array("tableid", "seatid"));
	if(!$user['tableid']){
		return false;
	}
	
	$tableid = $user['tableid'];
	$seatid = $user['seatid'];
	$seat = json_decode($redis->hget("table:$tableid", "seat-$seatid"), true);
	if(isset($seat['look'])){
		return false;
	}
	
	$seat['look'] = true;
	$redis->hset("table:$tableid", "seat-$seatid", json_encode($seat));
	
	$router = getRouter();
	$router->publish("table:$tableid", packMsg("look", array(
		"sid" => $sid
	)));
	
	response("look", array(
		'cards' => $seat['cards']
	));
}

//跟
function doFollow($msg)
{
	$sid = SID;
	$redis = getRedis();
	
	$user = $redis->hMget("user:$sid", array("tableid", "seatid", "gold"));
	if(!$user['tableid']){
		return false;
	}
	
	$tableid = $user['tableid'];
	$seatid = $user['seatid'];
	$seatkey = "seat-$seatid";
	$table = $redis->hgetall("table:$tableid");
	if(!$table['state']){
		return false;
	}
	
	$seats = explode(',', $table['seats']);
	if($seats[$table['current']] != $seatid){
		return false;
	}
	
	$seat = json_decode($table[$seatkey], true);
	if($seat['state']){
		return false;
	}
	
	$needpoint = $seat['look'] ? $table['point'] * 2 : $table['point'];
	if($user['gold'] < $needpoint){
		response("follow", array(
			"error" => 1
		));
		return false;
	}
	
	//update current
	$current = $table['current'];
	if(++$current >= count($seats)){
		$current = 0;
	}
	
	//update talbe info
	$seat['point']+= $needpoint;
	$redis->hmset("table:$tableid", array(
		$seatkey => json_encode($seat),
		'current' => $current,
		'total' => $table['total'] + $needpoint,
	));
	
	$router = getRouter();
	$router->publish("table:$tableid", packMsg('follow', array(
		'sid' => $sid,
		'current' => $current,
		'total' => $table['total'] + $needpoint,
	)));
}

//加注
function doRise($msg)
{
	$sid = SID;
	$redis = getRedis();
	
	$user = $redis->hMget("user:$sid", array("tableid", "seatid", "gold"));
	if(!$user['tableid']){
		return false;
	}
	
	$tableid = $user['tableid'];
	$seatid = $user['seatid'];
	$seatkey = "seat-$seatid";
	$table = $redis->hgetall("table:$tableid");
	if(!$table['state']){
		return false;
	}
	
	$seats = explode(',', $table['seats']);
	if($seats[$table['current']] != $seatid){
		return false;
	}
	
	$seat = json_decode($table[$seatkey], true);
	if($seat['state']){
		return false;
	}
	
	$point = $table['point'] * 2;
	$needpoint = $seat['look'] ? $point * 2 : $point;
	if($user['gold'] < $needpoint){
		response("follow", array(
			"error" => 1
		));
		return false;
	}
	
	//update current
	$current = $table['current'];
	if(++$current >= count($seats)){
		$current = 0;
	}
	
	//update talbe info
	$seat['point']+= $needpoint;
	$redis->hmset("table:$tableid", array(
		$seatkey => json_encode($seat),
		'current' => $current,
		'point' => $point,
		'total' => $table['total'] + $needpoint,
	));
	
	$router = getRouter();
	$router->publish("table:$tableid", packMsg('follow', array(
		'sid' => $sid,
		'current' => $current,
		'point' => $point,
		'total' => $table['total'] + $needpoint,
	)));
}

//比牌
function doCompare($msg)
{
	$sid = SID;
	$redis = getRedis();
	
	$user = $redis->hMget("user:$sid", array("tableid", "seatid", "gold"));
	if(!$user['tableid']){
		return false;
	}
	
	$tableid = $user['tableid'];
	$seatid = $user['seatid'];
	$seatkey = "seat-$seatid";
	$eneid = $msg['seatid'];
	$enekey = "seat-$eneid";
	if($eneid == $seatid){
		return false;
	}
	
	//get table
	$table = $redis->hgetall("table:$tableid");
	if(!$table['state']){
		return false;
	}
	
	//check current
	$seats = explode(',', $table['seats']);
	if($seats[$table['current']] != $seatid){
		return false;
	}
	
	//check state
	$seat = json_decode($table[$seatkey], true);
	if($seat['state']){
		return false;
	}
	
	//check state
	$ene = json_decode($table[$enekey], true);
	if($ene['state']){
		return false;
	}
	
	//update current
	$current = $table['current'];
	if(++$current >= count($seats)){
		$current = 0;
	}
	
	//compare
	$ret = compareCard($seat['cards'], $ene['cards']);
	$winner = null;
	$update = array();
	if($ret <= 0){
		$winner = $ene['sid'];
		$seat['state'] = 2;
		$update[$seatkey] = json_encode($seat);
	}else{
		$winner = $sid;
		$ene['state'] = 2;
		$update[$enekey] = json_encode($ene);
	}
	
	//结束
	if(--$table['users'] <= 1){
		$update['state'] = 0;
	}
	
	$update['users'] = $table['users'];
	$update['current'] = $current;
	$redis->hmset("table:$tableid", $update);
	
	$router = getRouter();
	$router->publish("table:$tableid", packMsg("compare", array(
		"winner" => $winner,
		"current" => $current,
	)));
	
	if(!$update['state']){
		$table['seats'] = $seats;
		$table['winner'] = $winner;
		gameover($table);
	}
}

//放弃
function doDiscard($msg)
{
	$sid = SID;
	$redis = getRedis();
	
	$user = $redis->hMget("user:$sid", array("tableid", "seatid", "gold"));
	if(!$user['tableid']){
		return false;
	}
	
	$tableid = $user['tableid'];
	$seatid = $user['seatid'];
	$seatkey = "seat-$seatid";
	$table = $redis->hgetall("table:$tableid");
	if(!$table['state']){
		return false;
	}
	
	$seats = explode(',', $table['seats']);
	if($seats[$table['current']] != $seatid){
		return false;
	}
	
	$seat = json_decode($table[$seatkey], true);
	if($seat['state']){
		return false;
	}
	$seat['state'] = 1;
	
	//update current
	$current = $table['current'];
	if(++$current >= count($seats)){
		$current = 0;
	}
	
	//update users
	$over = false;
	if(--$table['users'] <= 1){
		$over = true;
	}
	
	//update talbe info
	$redis->hmset("table:$tableid", array(
		$seatkey => json_encode($seat),
		'current' => $current,
		'users' => $table['users'],
	));
	
	$router = getRouter();
	$router->publish("table:$tableid", packMsg('discard', array(
		'sid' => $sid,
		'current' => $current,
	)));
	
	//over
	if($over){
		
	}
}

function gameover($table)
{
	$redis = getRedis();
	$update = array();
	$winner = $table['winner'];
	foreach($table['seats'] as $k){
		$seat = json_decode($table["seat-$k"], true);
		$u = $seat['sid'];
		$v = -$seat['point'];
		if($seat['sid'] == $winner){
			$v = $table["total"] - $seat['point'];
		}else{
			$v = -$seat['point'];
		}
		
		$redis->hIncrBy("user:$u", "gold", $v);
		$update[$seat['sid']] = $v;
	}
	
	$router->publish("table:$tableid", packMsg("over", array(
		"winner" => $winner,
		'update' => $update,
	)));
}

function unpackMsg($data)
{
	$msg = json_decode($data);
	return $msg;
}

function packMsg($type, $data)
{
	return json_encode(array(
		'type' => $type,
		'data' => $data
	));
}

function response($type, $data)
{
	$body = packMsg($type, $data);
	if(FOOKING){
		header("Content-Length: " . strlen($body));
	}
	echo $body;
}

//获取redis
function getRedis()
{
	static $redis = null;
	if($redis === null){
		$redis = new Redis();
		$redis->connect(REDIS_HOST, REDIS_PORT);
	}
	return $redis;
}

//获取router
function getRouter()
{
	static $router = null;
	if($router === null){
		$router = new RouterClient(ROUTER_HOST, ROUTER_PORT);
	}
	return $router;
}

function makeCard()
{
	$cards = range(1, 52);
	shuffle($cards);
	return $cards;
}

function compareCard($cards)
{
	return 0;
}

function getCardInfo($data)
{
	//转换
	$cards = array();
	foreach($data as $num){
		$card = $num % 13 ? $num % 13 : 13;
		$color = ceil($num / 13);
		$cards[] = array(
			'card' => $card,
			'color' => $color,
			'number' => $num
		);
	}
	
	//排序
	usort($cards, function($a, $b){
		if($a['card'] == $b['card']){
			return 0;
		}else if($a['card'] < $b['card']){
			return -1;
		}else{
			return 1;
		}
	});
	
	$len = count($cards);
	$sameNum = true;//同号
	$sameColor = true;//同色
	$order = true;//连号
	$pair = false;//对子
	$pairNum = null;//对子号
	$lastNum = 0;
	$lastColor = 0;
	$min = $max = 0;
	foreach($cards as $card){
		$color = $card['color'];
		$number = $card['card'];

		if($lastNum == 0){
			$lastNum = $number;
			$lastColor = $color;
			$min = $max = $number;
			continue;
		}
		
		if($number < $min){
			$min = $number;
		}
		
		if($number > $max){
			$max = $number;
		}
		
		if($sameNum && $number != $lastNum){
			$sameNum = false;
		}
		
		if($sameColor && $color != $lastColor){
			$sameColor = false;
		}
		
		if($order && $number != $lastNum + 1){
			$order = false;
		}
		
		if(!$pair && $number == $lastNum){
			$pair = true;
			$pairNum = $number;
		}
		
		$lastNum = $number;
		$lastColor = $color;
	}

	if($sameNum){//炸弹
		$type = 6;
		$min = $cards[0]['card'];
		$max = $cards[0]['card'];
	}else if($sameColor && $order){//同花顺
		$type = 5;
		$min = $cards[0]['card'];
		$max = $cards[$len - 1]['card'];
	}else if($sameColor){//同花
		$type = 4;
		$min = $cards[0]['card'];
		$max = $cards[$len - 1]['card'];
	}else if($order){//顺子
		$type = 3;
		$min = $cards[0]['card'];
		$max = $cards[$len - 1]['card'];
	}else if($pair){//对子
		$type = 2;
		$max = (($pairNum == $min) ? $max : $min);
		$min = $pairNum;
	}else{//单张
		$type = 1;
		$min = $cards[0]['card'];
		$max = $cards[$len - 1]['card'];
	}
	
	return array(
		'type' => $type,
		'min' => $min,
		'max' => $max,
		'cards' => $cards,
	);
}